// http
package web

import (
	"encoding/json"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"strconv"
	"sync"
	"xlog/common"
)

var mutex sync.RWMutex

var jsDomain string = "www.pconline.com.cn"

func checkError(err error) {
	if err != nil {
		log.Println("Fatal error ", err.Error())
		return
	}
}

//totalinfo
var InfoTotal map[string]int64
var InfoTotal2 map[string]string

func TotalInfo(w http.ResponseWriter, r *http.Request) {
	InfoTotal = make(map[string]int64)
	InfoTotal2 = make(map[string]string)
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Content-Type", "application/json")
	r.ParseForm()
	switch r.Form.Get("key") {
	case "totalbyte":
		InfoTotal["totalbyte"] = bodyBytesTotal / 1024 / 1024
		jsonStr, err := json.Marshal(InfoTotal)
		checkError(err)
		fmt.Fprintf(w, "%s", jsonStr)
	case "totalrequest":
		InfoTotal["totalrequest"] = total
		jsonStr, err := json.Marshal(InfoTotal)
		checkError(err)
		fmt.Fprintf(w, "%s", jsonStr)
	case "avgreqtime":
		InfoTotal2["avgreqtime"] = strconv.FormatFloat(timeSecondsTotal/float64(total), 'f', 3, 64)
		jsonStr, err := json.Marshal(InfoTotal2)
		checkError(err)
		fmt.Fprintf(w, "%s", jsonStr)
	case "load":
		mutex.Lock()
		defer mutex.Unlock()
		InfoTotal2["load"] = readload()
		jsonStr, err := json.Marshal(InfoTotal2)
		checkError(err)
		fmt.Fprintf(w, "%s", jsonStr)
	default:
		fmt.Fprintf(w, "nosupport")
	}
}

func InfoDist(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Content-Type", "application/json")
	var islist bool
	r.ParseForm()
	if r.Form.Get("percent") == "true" {
		islist = true
	}
	switch r.Form.Get("key") {
	case "useragent":
		fmt.Fprintf(w, common.PrintMapjson(uaCounterTotal.Map, total, 20, islist))
	case "filteruseragent":
		fmt.Fprintf(w, common.PrintMapjson(uaCounterFiltered.Map, total, 13, islist))
	case "reqtime":
		fmt.Fprintf(w, common.PrintMapjson(timeDistCounterTotal.Map, total, 20, islist))
	case "method":
		fmt.Fprintf(w, common.PrintMapjson(methodCounterTotal.Map, total, 20, islist))
	case "host":
		fmt.Fprintf(w, common.PrintMapjson(hostCounterTotal.Map, total, 13, islist))
	case "statuscode":
		fmt.Fprintf(w, common.PrintMapjson(statusCodeCounterTotal.Map, total, 13, islist))
	case "remoteaddress":
		fmt.Fprintf(w, common.PrintMapjson(raIPCounterTotal.Map, total, 13, islist))
	case "xff":
		fmt.Fprintf(w, common.PrintMapjson(xffIPCounterTotal.Map, total, 13, islist))
	case "requri":
		fmt.Fprintf(w, common.PrintMapjson(uriCounterTotal.Map, total, 13, islist))
	case "rawuri":
		fmt.Fprintf(w, common.PrintMapjson(rawUriCounterTotal.Map, total, 13, islist))
	case "filterrawuri":
		fmt.Fprintf(w, common.PrintMapjson(rawUriCounterFiltered.Map, total, 13, islist))
	case "uript":
		fmt.Fprintf(w, common.PrintMapjson(uriPtCounterTotal.Map, total, 13, islist))
	case "referer":
		fmt.Fprintf(w, common.PrintMapjson(rfCounterTotal.Map, total, 13, islist))
	default:
		fmt.Fprintf(w, "nosupport")
	}
}

func BodyByteDist(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Content-Type", "application/json")
	r.ParseForm()

	switch r.Form.Get("key") {
	case "host":
		fmt.Fprintf(w, common.PrintMapjson2(bodyBytesHostCounterTotal.MapHttp, bodyBytesTotal, 18))
	case "remoteaddress":
		fmt.Fprintf(w, common.PrintMapjson2(bodyBytesIpCounterTotal.MapHttp, bodyBytesTotal, 18))
	case "rawuri":
		fmt.Fprintf(w, common.PrintMapjson2(bodyBytesUriCounterTotal.MapHttp, bodyBytesTotal, 18))
	default:
		fmt.Fprintf(w, "nosupport")
	}
}

func InfoTrend(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Content-Type", "application/json")
	r.ParseForm()
	switch r.Form.Get("key") {
	case "useragent":
		fmt.Fprintf(w, trendCounter.UserAgentTrend(r.Form.Get("ualist")))
	case "time":
		fmt.Fprintf(w, trendCounter.VtimeTrend())
	case "countip":
		fmt.Fprintf(w, trendCounter.CipTrend())
	case "statuscode":
		fmt.Fprintf(w, trendCounter.StatusCodeTrend(r.Form.Get("codelist")))
	case "bodybyte":
		fmt.Fprintf(w, trendCounter.ByteTrend())
	default:
		fmt.Fprintf(w, "nosupport")
	}
}

func Index(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	t, err := template.New("index template").Parse(TempIndexHtml)
	checkError(err)
	data := struct {
		Title  string
		Domain string
	}{
		Title:  "xlog demo",
		Domain: jsDomain,
	}
	err = t.Execute(w, data)
	checkError(err)
}

func StatusCode(w http.ResponseWriter, r *http.Request) {
	t, err := template.New("statscode template").Parse(TempScHtml)
	checkError(err)
	data := struct {
		Title  string
		Domain string
	}{
		Title:  "xlog statscode",
		Domain: jsDomain,
	}
	err = t.Execute(w, data)
	checkError(err)
}

func UserAgent(w http.ResponseWriter, r *http.Request) {
	t, err := template.New("useragent template").Parse(TempUaHtml)
	checkError(err)
	data := struct {
		Title  string
		Domain string
	}{
		Title:  "xlog useragent",
		Domain: jsDomain,
	}
	err = t.Execute(w, data)
	checkError(err)
}

func RemoteAddress(w http.ResponseWriter, r *http.Request) {
	t, err := template.New("remoteaddress template").Parse(TempRaHtml)
	checkError(err)
	data := struct {
		Title  string
		Domain string
	}{
		Title:  "xlog IP",
		Domain: jsDomain,
	}
	err = t.Execute(w, data)
	checkError(err)
}

func ReqUri(w http.ResponseWriter, r *http.Request) {
	t, err := template.New("requesturi template").Parse(TempUriHtml)
	checkError(err)
	data := struct {
		Title  string
		Domain string
	}{
		Title:  "xlog RequestUri",
		Domain: jsDomain,
	}
	err = t.Execute(w, data)
	checkError(err)
}

func Referer(w http.ResponseWriter, r *http.Request) {
	t, err := template.New("referer template").Parse(TempRfHtml)
	checkError(err)
	data := struct {
		Title  string
		Domain string
	}{
		Title:  "xlog Referer",
		Domain: jsDomain,
	}
	err = t.Execute(w, data)
	checkError(err)
}

func BodyByte(w http.ResponseWriter, r *http.Request) {
	t, err := template.New("bodybyte template").Parse(TempByteHtml)
	checkError(err)
	data := struct {
		Title  string
		Domain string
	}{
		Title:  "xlog BodyByte",
		Domain: jsDomain,
	}
	err = t.Execute(w, data)
	checkError(err)
}

func ChinaMaps(w http.ResponseWriter, r *http.Request) {
	t, err := template.New("china maps").Parse(TempMapsHtml)
	checkError(err)
	data := struct {
		Title  string
		Domain string
	}{
		Title:  "china maps",
		Domain: jsDomain,
	}
	err = t.Execute(w, data)
	checkError(err)
}

//中国地图的json数据
func MapDist(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Content-Type", "application/json")
	//r.ParseForm()
	fmt.Fprintf(w, common.PrintChinaMap())
}

//堆叠柱形图总的地区json数据
func AreaCountDist(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Content-Type", "application/json")
	r.ParseForm()
	fmt.Fprintf(w, common.PrintCountMap(r.Form.Get("key")))
}

//堆叠柱形图大于3秒地区json数据
func Gt3AreaCountDist(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Content-Type", "application/json")
	r.ParseForm()
	fmt.Fprintf(w, common.PrintGt3CountMap(r.Form.Get("key")))
}

func Handle(port string) {
	http.HandleFunc("/totalinfo", TotalInfo)               //json接口
	http.HandleFunc("/infodist", InfoDist)                 //json接口
	http.HandleFunc("/bodybytedist", BodyByteDist)         //json接口
	http.HandleFunc("/infotrend", InfoTrend)               //json接口
	http.HandleFunc("/mapdist", MapDist)                   //json接口
	http.HandleFunc("/areacountdist", AreaCountDist)       //json接口
	http.HandleFunc("/gt3areacountdist", Gt3AreaCountDist) //json接口
	http.HandleFunc("/useragent", UserAgent)               //页面
	http.HandleFunc("/statuscode", StatusCode)             //页面
	http.HandleFunc("/remoteaddress", RemoteAddress)       //页面
	http.HandleFunc("/requesturi", ReqUri)                 //页面
	http.HandleFunc("/referer", Referer)                   //页面
	http.HandleFunc("/bodybytes", BodyByte)                //页面
	http.HandleFunc("/chinamaps", ChinaMaps)               //页面
	//http.HandleFunc("/areacount", AreaCount)         //页面
	http.HandleFunc("/", Index) //页面
	http.ListenAndServe("0.0.0.0:"+port, nil)
}
